﻿
using System;
using System.Linq;

using SubSonic;

namespace TestDB.Data
{
    public partial class FaultItem
    {
        // ============================================ //
        #region [ member variables ]

        /// <summary>
        /// when generating id for each row, there are two options:
        /// 1. set auto-incremental id column in the table, and retrieve that id back after successful insertion
        /// 2. we generate the unique id by ourself
        /// 
        /// Though option 1 is very easy, but that method limits us that we can only insert the rows one by one
        /// if we use batch insertion, these auto-generated ids will be ignored
        /// 
        /// so here we apply the second option, that is, keep a static field for each table
        /// and generate id for each row by increasing that static field by one before inserting the row
        /// </summary>
        private static int m_currentId = 0;// uint is useless, because this.FaultItemId is just int

        #endregion

        // ============================================ //
        public void GenerateId()
        {
            if (this.FaultItemId <= 0)
            {
                m_currentId = checked(m_currentId + 1);
                this.FaultItemId = m_currentId;
            }
        }

        // ============================================ //
        #region [ override virtual methods ]

        protected override void BeforeInsert()
        {
            base.BeforeInsert();
            GenerateId();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (this == obj)
                return true;

            if (obj.GetType() != typeof(FaultItem))
                return false;

            FaultItem otherItem = (FaultItem)obj;
            return (this.FaultItemId == otherItem.FaultItemId)
                && (this.FaultListId == otherItem.FaultListId)
                && (this.FaultType == otherItem.FaultType)
                && (CommonFunctions.IsEqual(this.Time, otherItem.Time))
                && (CommonFunctions.IsEqual(this.FaultValue, otherItem.FaultValue));
        }

        public override int GetHashCode()
        {
            return this.FaultItemId;
        }

        #endregion
    }

    public partial class FaultList
    {
        // ============================================ //
        #region [ member variables ]

        private static int m_currentId = 0;

        private FaultItemCollection m_faultItems;

        #endregion

        // ============================================ //
        #region [ id management ]

        public void GenerateId()
        {
            if (this.FaultListId <= 0)
            {
                m_currentId = checked(m_currentId + 1);
                this.FaultListId = m_currentId;
            }

            foreach (FaultItem item in m_faultItems)
            {
                if (item.FaultListId != this.FaultListId)
                    item.FaultListId = this.FaultListId;
            }
        }

        #endregion

        // ============================================ //
        #region [ override virtual methods ]

        protected override void BeforeInsert()
        {
            base.BeforeInsert();
            GenerateId();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (this == obj)
                return true;

            if (obj.GetType() != typeof(FaultList))
                return false;

            FaultList otherlist = (FaultList)obj;

            bool isequal = (this.FaultListId == otherlist.FaultListId) && (CommonFunctions.IsEqual(this.Name, otherlist.Name));
            if (isequal)
            {
                FaultItemCollection selfCollection = this.FaultItemsContained;
                FaultItemCollection otherCollection = otherlist.FaultItemsContained;

                int count = selfCollection.Count;
                if (otherCollection.Count != count)
                    return false;
                else
                {
                    for (int index = 0; index < count; ++index)
                    {
                        if (!selfCollection[index].Equals(otherCollection[index]))
                            return false;
                    }
                }
            }
            return true;
        }

        public override int GetHashCode()
        {
            return this.FaultListId;
        }

        #endregion

        // ============================================ //
        #region [ fault items management ]

        /// <summary>
        /// in the implementation of this property, a "Lazy Loading" strategy is used
        /// </summary>
        public FaultItemCollection FaultItemsContained
        {
            get
            {
                InitFaultItems();
                return m_faultItems;
            }
        }

        private void InitFaultItems()
        {
            if (m_faultItems == null)
            {
                m_faultItems = this.IsNew ? new FaultItemCollection() : FaultItemRecords();
            }// if
        }

        public void AddFaultItem(FaultItem item)
        {
            InitFaultItems();

            item.GenerateId();

            if (!m_faultItems.Any(x => x.FaultItemId == item.FaultItemId))
            {
                m_faultItems.Add(item);
            }
        }

        public void RemoveFaultItem(int faultitemId)
        {
            InitFaultItems();

            // the element found out is just the same as the element in the container
            // not a copy with the same content
            FaultItem item = (from x in m_faultItems
                              where x.FaultItemId == faultitemId
                              select x).SingleOrDefault();
            if (item != null)
                m_faultItems.Remove(item);
        }

        #endregion

        // ============================================ //
        #region [ extend DB operation ]

        /// <summary>
        /// save FaultList and its related FaultItems
        /// abandon the original plan that invoke "BatchSave" in "AfterCommit"
        /// because if no column of "FaultList" is changed but existing related FaultItem is changed
        /// or new FaultItem is inserted, current "FauultList" will not be marked as dirty
        /// and Save() will just exit beforing calling "AfterCommit"
        /// so I invent a new method called "SaveAll" to fufill this function
        /// </summary>
        public void SaveAll()
        {
            Save();

            m_faultItems.BatchSave();
            foreach (FaultItem item in m_faultItems)
            {
                item.MarkOld();
                item.MarkClean();
            }
        }

        public void DeleteAll()
        {
            // first delete related children items
            SqlQuery cmd = DB.Delete().From(FaultItem.Schema).Where(FaultItem.Columns.FaultListId).IsEqualTo(this.FaultListId);
            cmd.Execute();

            // then delete local record
            FaultList.Delete(this.FaultListId);
        }

        #endregion
    }
}